﻿namespace Chameleon.Collections
{
	using System;
	using System.Collections;
	using System.Collections.Generic;

	/// <summary>
	/// Notifies clients when items are enumerated.
	/// </summary>
	/// <typeparam name="T">Type of the items to be enumerated.</typeparam>
	
	internal class InterceptedEnumerator<T> : IEnumerator<T>
	{
		#region Events

			/// <summary>
			/// Event raised when an item has been enumerated.
			/// </summary>
			
			internal event EventHandler<InterceptedEnumerationEventArgs> Enumerated = delegate {};

		#endregion


		#region Fields

			/// <summary>
			/// Enumerator whose items to intercept.
			/// </summary>
			
			IEnumerator<T> Enumerator;

		#endregion


		#region IDisposable

			/// <summary>
			/// Performs tasks associated with freeing, releasing, or resetting unmanaged resources.
			/// </summary>
			
			public void Dispose()
			{
				Enumerator.Dispose();
			}

		#endregion


		#region IEnumerator

			/// <summary>
			/// Gets the element in the collection at the current position of the enumerator.
			/// </summary>
			
			public T Current
			{
				get { return InterceptCurrent(); }
			}


			/// <summary>
			/// Gets the element in the collection at the current position of the enumerator.
			/// </summary>

			object IEnumerator.Current
			{
				get { return Current; }
			}


			/// <summary>
			/// Advances the enumerator to the next element of the collection.
			/// </summary>
			/// <returns>
			/// True if the enumerator was successfully advanced to the next element; 
			/// False if the enumerator has passed the end of the collection.
			/// </returns>

			public bool MoveNext()
			{
				return Enumerator.MoveNext();
			}


			/// <summary>
			/// Sets the enumerator to its initial position, which is before the first element in the collection.
			/// </summary>

			public void Reset()
			{
				Enumerator.Reset();
			}

		#endregion


		#region Methods

			/// <summary>
			/// Notifies clients that an item has been enumerated.
			/// </summary>
			/// <param name="item">Item that was enumerated.</param>
			
			void OnEnumerated( T item )
			{
				Enumerated( this, new InterceptedEnumerationEventArgs( item ) );
			}


			/// <summary>
			/// Returns the enumerator's current item after notifying clients of its interception.
			/// </summary>

			T InterceptCurrent()
			{
				var item = Enumerator.Current;

				OnEnumerated( item );
				return item;
			}

		#endregion


		#region Constructors

			/// <summary>
			/// Initializes a new instance to intercept items iterated by the specified enumerator.
			/// </summary>
			/// <param name="enumerator">Enumerator whose items to intercept.</param>
			/// <param name="enumerated">Event handler for the Enumerated event.</param>
			
			internal InterceptedEnumerator( IEnumerator<T> enumerator, EventHandler<InterceptedEnumerationEventArgs> enumerated )
			{
				Enumerator = enumerator;
				Enumerated += enumerated;
			}

		#endregion
	}
}
